home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 3 / BBS in a box - Trilogy III.iso / Files / Prog / U-Z / VideoToolBox Folder / VideoToolboxSources / ReadMatLabFile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-27  |  9.4 KB  |  343 lines  |  [TEXT/KAHL]

  1. /*
  2. ReadMatLabFile.c - load/save a matrix from/to a MatLab file.
  3.  
  4. Note: these functions are indepedent of MatLab itself. You can use these
  5. functions from with a stand-alone C application, or from within a MATLAB file,
  6. i.e. a MatLab code resource.
  7.  
  8. This example loads two matrices from a MatLab file:
  9.  
  10.     FILE *f;
  11.     char name[64];
  12.     long rows,cols;
  13.     double *xr,*xi;
  14.     short *mr,*mi;
  15.     int error;
  16.     f = fopen("foo.mat","rb");
  17.     error=LoadMatDoubles(f,name,&rows,&cols,&xr,&xi);// Read 8-byte doubles into doubles
  18.     error=LoadMatShorts(f,name,&rows,&cols,&mr,&mi); // Read 8-byte doubles into shorts
  19.     fclose(f);
  20.     free(xr);
  21.     free(xi);
  22.     free(mr);
  23.     free(mi);
  24.  
  25. This example saves four matrices to disk, creating a MatLab file:
  26.  
  27.     FILE *fp;
  28.     double xyz[1000],ar[1000],ai[1000];
  29.     short m[100],n[100];
  30.     fp = fopen("bar.mat","wb");
  31.     SetFileInfo("bar.mat",'MATW','MATL');
  32.     error=SaveMatDoubles(fp,"xyz",2,3,xyz,NULL);    // real
  33.     error=SaveMatShorts(fp,"m",2,3,m,NULL);            // real
  34.     error=SaveMatDoubles(fp,"a",5,5,ar,ai);            // complex
  35.     error=SaveMatShorts(fp,"mc",2,3,m,n);            // complex
  36.     fclose(fp);
  37.  
  38. The LoadMatXXX and SaveMatXXX routines return 0 if successful and 1 if they
  39. fail.  They can be called repeatedly until they fail (e.g. end of file is
  40. reached). The two array pointers will be NULL after calling LoadMatXXX unless
  41. they are loaded. The second (imaginary) pointer will be NULL unless the matrix
  42. was complex. Similarly, when you call SaveMatXXX you indicate a real matrix by
  43. supplying a NULL second pointer.
  44.  
  45. PROTOTYPES:
  46. int LoadMatDoubles(FILE *f,char *name,long *rows,long *cols
  47.     ,double **real,double **imag);            // read 8-byte DOUBLES into doubles
  48. int LoadMatShorts(FILE *f,char *name,long *rows,long *cols
  49.     ,short **real,short **imag);            // read 8-byte DOUBLES into shorts
  50. int SaveMatDoubles(FILE *f,char *name,long rows,long cols
  51.     ,double *real,double *imag);            // write doubles as 8-byte DOUBLES
  52. int SaveMatShorts(FILE *f,char *name,long rows,long cols
  53.     ,short *real,short *imag);                // write shorts as shorts
  54.  
  55. There is a slight asymmetry here that you should be aware of. SaveMatShorts()
  56. produces a (compact) MatLab file made up of shorts, but the LoadMatShorts() will
  57. only read a (big) MatLab file made up of 8-byte doubles. So you won't always be
  58. able to read from C the file you wrote from C. The reason for this is that while
  59. the MatLab "Load" command supports all the MatLab file formats, the MatLab
  60. "Save" command has no provision for specifying (binary) file formats and thus
  61. always uses format type 0, 8-byte short doubles, so I didn't bother to implement
  62. any routines to read any other format.
  63.  
  64. HISTORY:
  65. 11-3-86 J.N. Little wrote loadmat.c and savemat.c
  66.  
  67. [14-Feb-91] jmb -- Added support for MPW C 3.x and THINK C.
  68.  
  69. 1/4/93    dgp Renamed MatLab.c. DOUBLE is now used soley within the
  70. new WriteXXX and ReadXXX subroutines. C users now only deal with double and short
  71. arrays; necessary conversions are done behind the scenes. double is faster and
  72. more convenient for Macintosh programming than the 8-byte short double used in
  73. the MatLab files. Added support for file format 3: signed short ints. Omitted
  74. the imagf flag since it's redundant. Omitted the type argument by supplying
  75. several user-callable front ends, each tailored to a particular number type.
  76.  
  77. 2/93 dgp Renamed ReadMatLabFile.c
  78. */
  79. #include "VideoToolbox.h"
  80. #include <assert.h>
  81.  
  82. double *ReadDoubles(FILE *f,long elements,char *name);
  83. short *ReadDoublesIntoShorts(FILE *f,long elements,char *name);
  84. int WriteDoubles(FILE *f,long elements,char *name,double *d);
  85. int WriteShorts(FILE *f,long elements,char *name,short *d);
  86. int LoadMat(FILE *f,char *name,long *rows,long *cols
  87.     ,void **real,void **imag,long *fileType,long desiredNumberType);
  88. int SaveMat(FILE *f,char *name,long rows,long cols,void *real,void *imag,long type);
  89.  
  90. typedef struct {
  91.      long type;        /* type */
  92.      long rows;        /* row dimension */
  93.      long cols;        /* column dimension */
  94.      long imagf;    /* flag indicating imag part */
  95.      long namlen;    /* name length (including NULL) */
  96. } Fmatrix;
  97.  
  98. /* From cmex.h */
  99. // MatLab files with number format 0 use 8-byte floating point numbers, which
  100. // we'll call DOUBLE.
  101. #undef DOUBLE
  102. #ifdef THINK_C
  103.     #define DOUBLE short double
  104. #else
  105.     #define DOUBLE double
  106. #endif
  107.  
  108.  
  109. LoadMatDoubles(FILE *f,char *name,long *rows,long *cols
  110.     ,double **real,double **imag)
  111. {
  112.     long fileType,desiredNumberType=0;
  113.     
  114.     return LoadMat(f,name,rows,cols,(void **)real,(void **)imag
  115.         ,&fileType,desiredNumberType);
  116. }
  117.     
  118. LoadMatShorts(FILE *f,char *name,long *rows,long *cols
  119.     ,short **real,short **imag)
  120. {
  121.     long fileType,desiredNumberType=3;
  122.     
  123.     return LoadMat(f,name,rows,cols,(void **)real,(void **)imag
  124.         ,&fileType,desiredNumberType);
  125. }
  126.  
  127. int SaveMatDoubles(FILE *f,char *name,long rows,long cols,double *real,double *imag)
  128. {
  129.     return SaveMat(f,name,rows,cols,real,imag,0);
  130. }
  131.  
  132. int SaveMatShorts(FILE *f,char *name,long rows,long cols,short *real,short *imag)
  133. {
  134.     return SaveMat(f,name,rows,cols,real,imag,30);
  135. }
  136.     
  137. LoadMat(FILE *f,char *name,long *rows,long *cols
  138.     ,void **real,void **imag,long *fileType,long desiredNumberType)
  139. {
  140.     Fmatrix    x;
  141.     long elements,namlen,imagf,numberFormat;
  142.  
  143.     *real=*imag=NULL;
  144.  
  145.     // Get Fmatrix structure from file
  146.     if (fread((char *)&x,sizeof(Fmatrix),1,f) != 1) return 1;
  147.     *fileType = x.type;
  148.     *rows = x.rows;
  149.     *cols = x.cols;
  150.     namlen = x.namlen;
  151.     elements = x.rows * x.cols;
  152.  
  153.     if(x.type/1000!=1)return 1;        // not Macintosh-compatible binary format
  154.     if(x.type/100%10!=0)return 1;    // transposed
  155.     numberFormat=x.type/10%10;
  156.     if(numberFormat!=0)return 1;    // not 8-byte doubles
  157.  
  158.     // Get matrix name from file
  159.     if (fread(name,sizeof(char),namlen,f) != namlen) return 1;
  160.     
  161.     // Get Real part of matrix from file
  162.     switch(desiredNumberType){
  163.     case 0:
  164.         *real=ReadDoubles(f,elements,name);
  165.         break;
  166.     case 3:
  167.         *real=ReadDoublesIntoShorts(f,elements,name);
  168.         break;
  169.     default:
  170.         real=NULL;
  171.     }
  172.     if(*real==NULL)return 1;
  173.  
  174.     // Get Imag part of matrix from file, if it exists
  175.     if (x.imagf) {
  176.         switch(desiredNumberType){
  177.         case 0:
  178.             *imag=ReadDoubles(f,elements,name);
  179.             break;
  180.         case 3:
  181.             *imag=ReadDoublesIntoShorts(f,elements,name);
  182.             break;
  183.         }
  184.         if(*imag==NULL){
  185.             free(*real);
  186.             *real=NULL;
  187.             return 1;
  188.         }
  189.     }
  190.     return 0;
  191. }
  192.  
  193. int SaveMat(FILE *f,char *name,long rows,long cols,void *real,void *imag,long type)
  194. {
  195.     Fmatrix    x;
  196.     long elements;
  197.     int error;
  198.     int fileFormat;
  199.     
  200.     type%=100;    // not transposed
  201.     type+=1000;    // indicate Macintosh-compatible binary format
  202.     x.type = type;
  203.     x.rows = rows;
  204.     x.cols = cols;
  205.     if(imag==NULL)x.imagf=0;
  206.     else x.imagf=1;
  207.     x.namlen = strlen(name) + 1;
  208.     elements = x.rows * x.cols;
  209.  
  210.     if(x.type/1000!=1)return 1;        // not Macintosh-compatible binary format
  211.     if(x.type/100%10!=0)return 1;    // transposed
  212.     fileFormat=x.type/10%10;
  213.     if(fileFormat!=0 && fileFormat!=3)return 1; // neither 8-byte double, nor short
  214.  
  215.     fwrite(&x,sizeof(Fmatrix),1,f);
  216.     fwrite(name,sizeof(char),(long)x.namlen,f);
  217.     switch(fileFormat){
  218.     case 0:
  219.         error=WriteDoubles(f,elements,name,real);
  220.         break;
  221.     case 3:
  222.         error=WriteShorts(f,elements,name,real);
  223.         break;
  224.     default:
  225.         error=1;
  226.     }
  227.     if(error)return 1;
  228.     if (imag!=NULL) {
  229.         switch(fileFormat){
  230.         case 0:
  231.             error=WriteDoubles(f,elements,name,imag);
  232.             break;
  233.         case 3:
  234.             error=WriteShorts(f,elements,name,imag);
  235.             break;
  236.         default:
  237.             error=1;
  238.         }
  239.         if(error)return 1;
  240.     }
  241.     return 0;
  242. }
  243.  
  244. // Reads DOUBLES (8-byte short doubles) into doubles
  245. double *ReadDoubles(FILE *f,long elements,char *name)
  246. {
  247.     DOUBLE *D;
  248.     double *d;
  249.     long i,n,j;
  250.     const dSize=2048/sizeof(DOUBLE);    // Can be whatever you want. Bigger is faster.
  251.     
  252.     assert(sizeof(DOUBLE)==8);
  253.     D=(DOUBLE *)malloc(dSize*sizeof(DOUBLE));
  254.     if(D==NULL){
  255.         printf("\nError: not enough room for buffer\n");
  256.         return NULL;
  257.     }
  258.     if (!(d = (double *)malloc(elements*sizeof(*d)))) {
  259.         printf("\nError: Variable %s too big to load\n",name);
  260.         return NULL;
  261.     }
  262.     for(i=0;i<elements;){
  263.         if(dSize<elements-i)n=dSize;
  264.         else n=elements-i;
  265.         if(fread(D,sizeof(DOUBLE),n,f) != n) {
  266.             free(d);
  267.             free(D);
  268.             return NULL;
  269.         }
  270.         for(j=0;j<n;j++)d[i++]=D[j];    // convert DOUBLE to double
  271.     }
  272.     free(D);
  273.     return d;
  274. }
  275.  
  276. // Reads DOUBLES (8-byte short doubles) into shorts
  277. short *ReadDoublesIntoShorts(FILE *f,long elements,char *name)
  278. {
  279.     DOUBLE *D;
  280.     short *d;
  281.     long i,n,j;
  282.     const dSize=2048/sizeof(DOUBLE);    // Can be whatever you want. Bigger is faster.
  283.     
  284.     assert(sizeof(DOUBLE)==8);
  285.     D=(DOUBLE *)malloc(dSize*sizeof(DOUBLE));
  286.     if(D==NULL){
  287.         printf("\nError: not enough room for buffer\n");
  288.         return NULL;
  289.     }
  290.     if (!(d = (short *)malloc(elements*sizeof(*d)))) {
  291.         printf("\nError: Variable %s too big to load\n",name);
  292.         return NULL;
  293.     }
  294.     for(i=0;i<elements;){
  295.         if(dSize<elements-i)n=dSize;
  296.         else n=elements-i;
  297.         if(fread(D,sizeof(DOUBLE),n,f) != n) {
  298.             free(d);
  299.             free(D);
  300.             return NULL;
  301.         }
  302.         for(j=0;j<n;j++)d[i++]=D[j];    // convert DOUBLE to short
  303.     }
  304.     free(D);
  305.     return d;
  306. }
  307.  
  308. // Writes doubles as DOUBLES (8-byte short doubles)
  309. int WriteDoubles(FILE *f,long elements,char *name,double *d)
  310. {
  311.     DOUBLE *D;
  312.     long i,n,j;
  313.     const dSize=2048/sizeof(DOUBLE);    // Can be whatever you want. Bigger is faster.
  314.     
  315.     assert(sizeof(DOUBLE)==8);
  316.     if (d==NULL) return 1;
  317.     D=(DOUBLE *)malloc(dSize*sizeof(DOUBLE));
  318.     if(D==NULL){
  319.         printf("\nError: not enough room for buffer\n");
  320.         return 1;
  321.     }
  322.     for(i=0;i<elements;){
  323.         if(dSize<elements-i)n=dSize;
  324.         else n=elements-i;
  325.         for(j=0;j<n;j++)D[j]=d[i++];    // convert double to DOUBLE
  326.         if(fwrite(D,sizeof(DOUBLE),n,f) != n) {
  327.             free(D);
  328.             return 1;
  329.         }
  330.     }
  331.     free(D);
  332.     return 0;
  333. }
  334.  
  335. // Writes shorts as shorts
  336. int WriteShorts(FILE *f,long elements,char *name,short *d)
  337. {
  338.     assert(sizeof(short)==2);
  339.     if (d==NULL) return 1;
  340.     if(fwrite(d,sizeof(short),elements,f) != elements) return 1;
  341.     return 0;
  342. }
  343.